/* 处理特殊键的兼容性问题 */
UE.plugins["keystrokes"] = function () {
    var me = this;
    var collapsed = true;
    me.addListener("keydown", function (type, evt) {
        var keyCode = evt.keyCode || evt.which,
            rng = me.selection.getRange();

        //处理全选的情况
        if (
            !rng.collapsed &&
            !(evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) &&
            ((keyCode >= 65 && keyCode <= 90) ||
                (keyCode >= 48 && keyCode <= 57) ||
                (keyCode >= 96 && keyCode <= 111) ||
                {
                    13: 1,
                    8: 1,
                    46: 1
                }[keyCode])
        ) {
            var tmpNode = rng.startContainer;
            if (domUtils.isFillChar(tmpNode)) {
                rng.setStartBefore(tmpNode);
            }
            tmpNode = rng.endContainer;
            if (domUtils.isFillChar(tmpNode)) {
                rng.setEndAfter(tmpNode);
            }
            rng.txtToElmBoundary();
            //结束边界可能放到了br的前边，要把br包含进来
            // x[xxx]<br/>
            if (rng.endContainer && rng.endContainer.nodeType == 1) {
                tmpNode = rng.endContainer.childNodes[rng.endOffset];
                if (tmpNode && domUtils.isBr(tmpNode)) {
                    rng.setEndAfter(tmpNode);
                }
            }
            if (rng.startOffset == 0) {
                tmpNode = rng.startContainer;
                if (domUtils.isBoundaryNode(tmpNode, "firstChild")) {
                    tmpNode = rng.endContainer;
                    if (
                        rng.endOffset ==
                        (tmpNode.nodeType == 3
                            ? tmpNode.nodeValue.length
                            : tmpNode.childNodes.length) &&
                        domUtils.isBoundaryNode(tmpNode, "lastChild")
                    ) {
                        me.fireEvent("saveScene");
                        me.body.innerHTML = "<p>" + (browser.ie ? "" : "<br/>") + "</p>";
                        rng.setStart(me.body.firstChild, 0).setCursor(false, true);
                        me._selectionChange();
                        return;
                    }
                }
            }
        }

        //处理backspace
        if (keyCode == keymap.Backspace) {
            rng = me.selection.getRange();
            collapsed = rng.collapsed;
            if (me.fireEvent("delkeydown", evt)) {
                return;
            }
            var start, end;
            //避免按两次删除才能生效的问题
            if (rng.collapsed && rng.inFillChar()) {
                start = rng.startContainer;

                if (domUtils.isFillChar(start)) {
                    rng.setStartBefore(start).shrinkBoundary(true).collapse(true);
                    domUtils.remove(start);
                } else {
                    start.nodeValue = start.nodeValue.replace(
                        new RegExp("^" + domUtils.fillChar),
                        ""
                    );
                    rng.startOffset--;
                    rng.collapse(true).select(true);
                }
            }

            //解决选中control元素不能删除的问题
            if ((start = rng.getClosedNode())) {
                me.fireEvent("saveScene");
                rng.setStartBefore(start);
                domUtils.remove(start);
                rng.setCursor();
                me.fireEvent("saveScene");
                domUtils.preventDefault(evt);
                return;
            }
            //阻止在table上的删除
            if (!browser.ie) {
                start = domUtils.findParentByTagName(rng.startContainer, "table", true);
                end = domUtils.findParentByTagName(rng.endContainer, "table", true);
                if ((start && !end) || (!start && end) || start !== end) {
                    evt.preventDefault();
                    return;
                }
            }
        }
        //处理tab键的逻辑
        if (keyCode == keymap.Tab) {
            //不处理以下标签
            var excludeTagNameForTabKey = {
                ol: 1,
                ul: 1,
                table: 1
            };
            //处理组件里的tab按下事件
            if (me.fireEvent("tabkeydown", evt)) {
                domUtils.preventDefault(evt);
                return;
            }
            var range = me.selection.getRange();
            me.fireEvent("saveScene");
            for (
                var i = 0,
                    txt = "",
                    tabSize = me.options.tabSize || 4,
                    tabNode = me.options.tabNode || "&nbsp;";
                i < tabSize;
                i++
            ) {
                txt += tabNode;
            }
            var span = me.document.createElement("span");
            span.innerHTML = txt + domUtils.fillChar;
            if (range.collapsed) {
                range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
            } else {
                var filterFn = function (node) {
                    return (
                        domUtils.isBlockElm(node) &&
                        !excludeTagNameForTabKey[node.tagName.toLowerCase()]
                    );
                };
                //普通的情况
                start = domUtils.findParent(range.startContainer, filterFn, true);
                end = domUtils.findParent(range.endContainer, filterFn, true);
                if (start && end && start === end) {
                    range.deleteContents();
                    range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
                } else {
                    var bookmark = range.createBookmark();
                    range.enlarge(true);
                    var bookmark2 = range.createBookmark(),
                        current = domUtils.getNextDomNode(bookmark2.start, false, filterFn);
                    while (
                        current &&
                        !(
                            domUtils.getPosition(current, bookmark2.end) &
                            domUtils.POSITION_FOLLOWING
                        )
                        ) {
                        current.insertBefore(
                            span.cloneNode(true).firstChild,
                            current.firstChild
                        );
                        current = domUtils.getNextDomNode(current, false, filterFn);
                    }
                    range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select();
                }
            }
            domUtils.preventDefault(evt);
        }
        //trace:1634
        //ff的del键在容器空的时候，也会删除
        if (browser.gecko && keyCode == 46) {
            range = me.selection.getRange();
            if (range.collapsed) {
                start = range.startContainer;
                if (domUtils.isEmptyBlock(start)) {
                    var parent = start.parentNode;
                    while (
                        domUtils.getChildCount(parent) == 1 &&
                        !domUtils.isBody(parent)
                        ) {
                        start = parent;
                        parent = parent.parentNode;
                    }
                    if (start === parent.lastChild) evt.preventDefault();
                    return;
                }
            }
        }

        /* 修复在编辑区域快捷键 (Mac:meta+alt+I; Win:ctrl+shift+I) 打不开 chrome 控制台的问题 */
        browser.chrome &&
        me.on("keydown", function (type, e) {
            var keyCode = e.keyCode || e.which;
            if (
                ((e.metaKey && e.altKey) || (e.ctrlKey && e.shiftKey)) &&
                keyCode == 73
            ) {
                return true;
            }
        });
    });
    me.addListener("keyup", function (type, evt) {
        var keyCode = evt.keyCode || evt.which,
            rng,
            me = this;
        if (keyCode == keymap.Backspace) {
            if (me.fireEvent("delkeyup")) {
                return;
            }
            rng = me.selection.getRange();
            if (rng.collapsed) {
                var tmpNode,
                    autoClearTagName = ["h1", "h2", "h3", "h4", "h5", "h6"];
                if (
                    (tmpNode = domUtils.findParentByTagName(
                        rng.startContainer,
                        autoClearTagName,
                        true
                    ))
                ) {
                    if (domUtils.isEmptyBlock(tmpNode)) {
                        var pre = tmpNode.previousSibling;
                        if (pre && pre.nodeName != "TABLE") {
                            domUtils.remove(tmpNode);
                            rng.setStartAtLast(pre).setCursor(false, true);
                            return;
                        } else {
                            var next = tmpNode.nextSibling;
                            if (next && next.nodeName != "TABLE") {
                                domUtils.remove(tmpNode);
                                rng.setStartAtFirst(next).setCursor(false, true);
                                return;
                            }
                        }
                    }
                }
                //处理当删除到body时，要重新给p标签展位
                if (domUtils.isBody(rng.startContainer)) {
                    var tmpNode = domUtils.createElement(me.document, "p", {
                        innerHTML: browser.ie ? domUtils.fillChar : "<br/>"
                    });
                    rng.insertNode(tmpNode).setStart(tmpNode, 0).setCursor(false, true);
                }
            }

            //chrome下如果删除了inline标签，浏览器会有记忆，在输入文字还是会套上刚才删除的标签，所以这里再选一次就不会了
            if (
                !collapsed &&
                (rng.startContainer.nodeType == 3 ||
                    (rng.startContainer.nodeType == 1 &&
                        domUtils.isEmptyBlock(rng.startContainer)))
            ) {
                if (browser.ie) {
                    var span = rng.document.createElement("span");
                    rng.insertNode(span).setStartBefore(span).collapse(true);
                    rng.select();
                    domUtils.remove(span);
                } else {
                    rng.select();
                }
            }
        }
    });
};
